from urllib import urlopen
from StringIO import StringIO
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import ElementTree
from xml.etree.ElementTree import parse
from xml.dom import minidom

from trip import Trip, Itinerary

TM_WS_URL = 'http://maps5.trimet.org/maps/tpws/V1/tripplanner/appID/8EB2B259743166EF7569C6C78/format/xml?fromPlace={from}&toPlace={to}&Arr=D&time={time}&date={date}&Min=T&Walk=0.50&Mode=A'
TM_MAP_URL = 'http://maps.trimet.org?fromPlace={from}&toPlace={to}&Arr=D&time={time}&date={date}&Min=T&Walk=0.50&Mode=A&submit'
TM_WS_NS = '{http://maps.trimet.org/maps/model/xml}'


class TMTripParser(Trip):
    '''Parse the XML response from the TriMet Trip XML service (ATIS trip planning engine)

    '''

    def __init__(self, params):
        super(TMTripParser, self).__init__()
        self.ws_url = TM_WS_URL.format(**params).replace(' ', '%20')
        self.map_url = TM_MAP_URL.format(**params).replace(' ', '%20')
        self.get_trip()

    def find_stop_info_from_element(self, stop_el, ns=TM_WS_NS):
        el = self.find_elements(stop_el, ['stopId', 'description', 'pos'], ns)
        pos = self.find_elements(el['pos'], ['lon', 'lat'], ns)
        return {'id':el['stopId'].text, 'name':el['description'].text, 'lon':pos['lon'].text, 'lat':pos['lat'].text}

    def find_leg_elements(self, elem, ns=TM_WS_NS):
        leg = {}
        el = self.find_elements(list(elem), ['route', 'from', 'to'], ns)
        if el is not None:
            leg['route'] = self.find_element_value(el['route'], 'internalNumber', ns)
            leg['origin'] = self.find_stop_info_from_element(el['from'])
            leg['destination'] = self.find_stop_info_from_element(el['to'])
        return leg

    def get_trip(self, ns=TM_WS_NS):
        doc = urlopen(self.ws_url)
        tree = parse(doc)

        # parse out any error message  
        err = self.find_in_tree(tree, 'error', ns)
        if err:
            self.error = True
            self.message = self.find_element_value(err, 'message', ns)

        # if the trip has itineraries (no error) parse out that data into our trip object
        self.itineraries = []
        itineraries = self.find_in_tree(tree, 'itineraries', ns)
        if itineraries:
            for itin in itineraries:
                legs = []
                td = None
                # parse out each itinerary and save them in our trip object
                for elem in itin:
                    # there is one time-distance node per itinerary
                    if 'time-distance' in elem.tag:
                        td = elem

                    # pull out the transit leg elements and save those into an array (we're not interested in walking)
                    if 'leg' in elem.tag and 'ns:TransitLegType' in elem.attrib.values():
                        leg = self.find_leg_elements(elem)
                        legs.append(leg)

                # save off the itinerary into our trip's array of itineraries
                it = Itinerary(legs)
                it.set_values_from_element(td, ns)
                self.itineraries.append(it)

def main():
    params = {
        'from' : 'pdx',
        'to' : 'zoo',
        'time' : '12:00 pm',
        'date' : '12/22/2010',
    }
    trip = TMTripParser(params)
    print trip.message

if __name__ == '__main__':
    main()

